<?php
/**
 * @description : This is a class for FTP upload and download.
 *                give a path and do these.
 * @version     : 1.0
 * @author      : stephen.mo <stephen.mo@hotmail.com>
 * @date        : Nov 23,2010
 */

require_once('TVB/SSH/SSHAgent.php');

class BasedFTP {

    #ftp server using port at 21    
	private $ftp_connection;
    
    #sftp(ssh-server) server using port at 22, must need the some key to needn't input password.
    private $sftp_connection;
    
    #xml config content.
    private $infoArr;
    
    #define instance
    static public $instance;

    #construct class : get the all setting for H3G.
    public function __construct($xmlObj) {/*{{{*/
        $this->infoArr = $xmlObj;
    }/*}}}*/

    /**
     * @method-name : getInstance().
     * @parameters  : (mixed)$xml_content - the content of xml file.
     * @description : instance the class of OAuthModel().
     * @author      : stephen.mo <stephen.mo@hotmail.com>
     * @date        : Mar 25,2011 
     */
    static public function getInstance($xml_content) {/*{{{*/
        if (!isset(self::$instance) || empty(self::$instance)) { 
            $class = __CLASS__;
            self::$instance = new $class($xml_content)) ;
        }
        return self::$instance;
    }/*}}}*/


    /**
     * @method-name : connectFtp().
     * @parameter   : NULL (using $this->infoArr['remote']['ftp'].
     * @description : generate a connection from Ftp Server.
     * @return      : object.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 23,2010
     */
    public function connectFtp() {/*{{{*/
        //if this handle exists,then return,else re-connect to ftp server.
        if (isset($this->ftp_connection) && !empty($this->ftp_connection)) {
            return $this->ftp_connection;
        }

        //get xml config file content. 
        $ftpInfoArr = array();
        foreach($this->infoArr['remote']->ftp as $key=>$val) {
            $ftpInfoArr = (array)$val;
        }
        
        //build a connect id.
        $conn_id = (!empty($ftpInfoArr['port'])) 
				   ? ftp_connect($ftpInfoArr['host'], $ftpInfoArr['port']) 
			       : ftp_connect($ftpInfoArr['host']);

        if(!$conn_id) {
            error_log('['.date('Y-m-d H:i:s').']'.__METHOD__.' Failed to connect to HOST < '.$ftpInfoArr['host'].' > with PORT < '.$ftpInfoArr['port'].' >');
            return FALSE;
        }
        
        //login ftp server with username and passwd.
		$bool = ftp_login($conn_id, $ftpInfoArr['username'], $ftpInfoArr['password']);
        $this->ftp_connection = ($bool) ? $conn_id : null;
        if (empty($bool)) {
            error_log('['.date('Y-m-d H:i:s').']'.__METHOD__.' Failed to login Server <'.$ftpInfoArr['host'].'> using USER '.$ftpInfoArr['username']);
        }
		return $bool;
    }/*}}}*/

    /**
     * @method-name : downloadFileFromFtp().
     * @parameter   : (string)$local_file  - the local server file.
     * @parameter   : (string)$remote_file - the remote server file.
     * @parameter   : (mode)$mode  - what type when ftp server transfer the files.
     * @description : download a file from remote server to local server. means downloading.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 23,2010
     */
    public function downloadFileFromFtp($remote_file,$local_file=NULL,$mode = FTP_BINARY) {/*{{{*/
        if (!self::connectFtp()) return FALSE;
        if (empty($remote_file)) return FALSE;
        
        //if local file is null ,will save remote file to /tmp/ 
        if (empty($local_file)) {
            $local_file = '/tmp/tmp_file_'.date('Ymd').'.tmp';
        }
        
        //using passive mode.
        ftp_pasv($this->ftp_connection,TRUE);
        
        //get the files.
        if (@ftp_get($this->ftp_connection,$local_file,$remote_file,$mode)) {
            return TRUE; 
        }
        
        error_log('['.date('Y-m-d H:i:s').']'.__METHOD__.' Failed to download '.$remote_file.' From HOST ');
        return FALSE;
    }/*}}}*/
    
    /**
     * @method-name : getFileContentByFTP().
     * @parameter   : (string)$remote_file.
     * @parameter   : (string)$local_file.
     * @description : get a remote files' content.
     * @return      : mixed
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function getFileContentByFTP($remote_file,$local_file=NULL,$mode= FTP_BINARY) {/*{{{*/
        $result = array();
        if (empty($remote_file)) return NULL;
        if (self::downloadFileFromFtp($remote_file,$local_file,$mode) && is_file($local_file)) {
            $result = file($local_file);
            return $result;
        }
        return NULL;
    }/*}}}*/

    /**
     * @method-name : getFileContentBySFTP().
     * @parameter   : (string)$remote_file.
     * @parameter   : (string)$local_file.
     * @description : get a remote files' content.
     * @return      : mixed
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function getFileContentBySFTP($remote_file,$local_file=NULL) {/*{{{*/
        $result = array();
        if (empty($remote_file)) return NULL;
        if (self::downloadFileFromSftp($remote_file,$local_file) && is_file($local_file)) {
            $result = file($local_file);
            return $result;
        }
        return NULL;
    }/*}}}*/


    /**
     * @method-name : connectSftp().
     * @parameter   : NULL
     * @description : create a connection using sftp.
     * @return      : object
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function connectSftp() {/*{{{*/
        
        if (isset($this->sftp_connection) && !empty($this->connection)) {
            return $this->sftp_connection;
        }

        $sftpInfoArr = array();
        foreach($this->infoArr['remote']->sftp as $key=>$val) {
            $sftpInfoArr = (array)$val;
        }
        
		//SCP MEDIA FILES
        try {
            $ssh = new SSHAgent($sftpInfoArr['host'], $sftpInfoArr['port'], $sftpInfoArr['username'], $sftpInfoArr['public_key'], $sftpInfoArr['private_key'], $sftpInfoArr['passphrase']);
			$this->sftp_connection = $ssh;
			return (!$ssh)? null : true;
        }
        catch (Exception $e) {
			error_log(__CLASS__." ".__FUNCTION__." ".$e->getMessage());
			return null;
        }
        
    }/*}}}*/

    /**
     * @method-name : downloadFileFromSftp()
     * @parameter   : (string)$remote_file
     * @parameter   : (string)$local_file
     * @parameter   : (string)$mode
     * @description : download file from remote servers using sftp.
     * @return      : mixed
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function downloadFileFromSftp($remote_file,$local_file=NULL) {/*{{{*/
        if (!self::connectSftp()) return FALSE;
        if (empty($remote_file)) return FALSE;

        if (empty($local_file)) {
            $local_file = '/tmp/tmp_file_'.date('Ymd').'.tmp';
        }

        try {
            $ret = @$this->sftp_connection->receiveFile($remote_file,$local_file);
            if ($ret === FALSE) {
                error_log("[".date("Y-m-d H:i:s")."]".__CLASS__." Failed to dowload $local_file");
                return FALSE;
            }
            return TRUE;
        }
        catch (Exception $e) {
            error_log("[".date("Y-m-d H:i:s")."] Exception: ".$e->getMessage());
            return FALSE;
        }

        
    }/*}}}*/

    /**
     * @method-name : compH3GRecords().
     * @parameter   : (string)$source  - source file.
     * @parameter   : (string)$destination - destination file.
     * @description : comparsion two files .the source and destination.
     * @return      : array.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function compH3GRecords($type='FTP',$source=NULL,$destination=NULL) {/*{{{*/
        $type = strtoupper($type);

        if (empty($source) && empty($destination)) {
            $tmp_type      = strtolower($type);
            $basedir       = (isset($this->infoArr['remote']->{$tmp_type}->basedir)) ? $this->infoArr['remote']->{$tmp_type}->basedir : NULL;
            $supportPrefix = (isset($this->infoArr['remote']->{$tmp_type}->prefix)) ? $this->infoArr['remote']->{$tmp_type}->prefix : NULL;
            $supportSuffix = (isset($this->infoArr['remote']->{$tmp_type}->suffix->item)) ? (array)$this->infoArr['remote']->{$tmp_type}->suffix : NULL;
            if (empty($supportSuffix)) return FALSE;
            
            $result = array();
            $now_date = date('Ymd');
            foreach($supportSuffix['item'] as $val) {
                $tmp_key     = strtolower(substr($val,1));
                $remote_file = $basedir.'/'.$supportPrefix.$now_date.$val;
                $local_file  = '/tmp/'.AppConst::DEFAULT_H3G_FTP_FILE_PREFIX.$now_date.$val;

                $tmpArr      = ($type=='FTP') ? self::getFileContentByFTP($remote_file,$local_file) : self::getFileContentBySFTP($remote_file,$local_file);

                //get content from tmpArr.
                if (!empty($tmpArr)) {
                    $tmp_key = strtolower(substr($val,1));
                    foreach((array)$tmpArr as $tmp_val) {
                        $phone_num = array_slice(explode(',',$tmp_val),0,1);
                        $result[$tmp_key][] = (string)$phone_num[0];
                    }
                }
            }
        }

        //comparsion arrays.
        $result['diff'] = array();
        if (isset($result['txt']) && isset($result['ok'])) {
            $result['diff'] = array_diff($result['txt'],$result['ok']);
        }

        return $result;

    }/*}}}*/

    /**
     * @mehtod-name : closeFtp().
     * @parameter   : NULL
     * @description : close a ftp source.
     * @return      : NULL
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 23,2010
     */
    public function closeFtp() {/*{{{*/
		ftp_close($this->ftp_connection);
    }/*}}}*/

    /**
     * @method-name : transferFileByFtp()
     * @parameter   : (string)$startFile - the source file in FTP server.
     * @parameter   : (string)$targetFile - the target file in your call-server.
     * @parameter   : (string)$mode - what type when you transfer the files.
     * @description : transfer the file from source to destination server. means uploading.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 23,2010
     */
    public function transferFileByFtp($startFile,$targetFile,$mode = FTP_BINARY) {/*{{{*/
        if (empty($startFile)) return FALSE;
        if (empty($targetFile)) return FALSE;
		ftp_pasv($this->ftp_connection, true);
		return ftp_put($this->ftp_connection, $targetFile, $startFile, $mode) ;
    }/*}}}*/

    /**
     * @method-name : transferFileBySft().
     * @parameter   : (string)$startFile.
     * @parameter   : (string)$targetFile.
     * @parameter   : (string)$permision.
     * @description : upload a $startFile to server and names $targetFile.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public function transferFileBySftp($startFile,$targetFile,$permision = 0644){/*{{{*/

        try{
            $ret = $this->sftp_connection->sendFile($startFile, $targetFile);
            if($ret === FALSE){
                error_log('['.date('Y-m-d H:i:s').']'.__CLASS__." Failed to upload");
                return FALSE;
            }
            return true;
        }
        catch (Exception $e) {
            error_log('Exception: ' . $e->getMessage());
            return false;
        }

    }/*}}}*/
    
    /**
     * @method-name : sendBySSH().
     * @parameter   : (array)$ftpAccounts.
     * @parameter   : (string)$source.
     * @parameter   : (string)$dist
     * @description : send a file from $source to $dist by SSH
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public static function sendBySSH($ftpAccounts, $source, $dist){/*{{{*/
		
		try{
            $status = TRUE;
            foreach($ftpAccounts as $ftp){
                error_log("Making SSH Connection to ".$ftp['username']."@".$ftp['host'].":".$ftp['port']);
                $ssh = new SSHAgent($ftp['host'], $ftp['port'], $ftp['username'], $ftp['public_key'], $ftp['private_key'], $ftp['passphrase']);
                if($ssh){
                    error_log("Transfer begin....{$source} to {$dist}");
                    $ret = $ssh->sendFile($source, $dist);
                    if ($ret === FALSE) {
                        error_log(__CLASS__." ".__FUNCTION__." Failed to send file to ".$ftp['host']." to ".$dist);
                        $status = FALSE;
                    }

                }
            }

        }catch(Exception $e){
            $status = FALSE;
            error_log(__CLASS__." ".__FUNCTION__." ERROR: ".$e->getMessage());

        }
		return $status;
    }/*}}}*/
    
    /**
     * @method-name : sendByFTP().
     * @parameter   : (array)$ftpAccounts.
     * @parameter   : (string)$source.
     * @parameter   : (string)$dist
     * @description : send a file from $source to $dist by FTP 
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 24,2010
     */
    public static function sendByFTP($ftpAccounts, $source, $dist){/*{{{*/
		try{
			$f_status = TRUE;
			
			foreach($ftpAccounts as $ftp){
				$status = true;
				error_log("Making FTP Connection to ".$ftp['username']."@".$ftp['host'].":".$ftp['port']);
                            
				$conn = (!empty($ftp['port'])) ? ftp_connect($ftp['host'], $ftp['port']) : ftp_connect($ftp['host']);
				if($conn && ftp_login($conn, $ftp['username'], $ftp['password'])){
					$pasv_mode = (isset($ftp['pasv_mode']) && $ftp['pasv_mode']=="off") ? FALSE : TRUE;
					ftp_pasv($conn, $pasv_mode);
					if(isset($ftp['dest_dir']) && !empty($ftp['dest_dir'])){
                                                $dist = $ftp['dest_dir'].basename($dist);

                                        }					
					ftp_mkdir_recursive($conn, 0777, dirname($dist)) or die('An error while creating a directory occured.');
					$status =  ftp_put($conn, $dist, $source, FTP_BINARY) ;
					if(!$status){ 
						error_log("Fail to Upload File to ".$ftp['host'].":".$dist);
						$f_status = FALSE;
					}
					
					
				}else{
					error_log("Failed to make FTP connection to ".$ftp['host'].":".$ftp['port']);
					$f_status = false;
				}
			}
			return $f_status;
		}catch(Exception $e){
			
                        error_log(__CLASS__." ".__FUNCTION__." ERROR: ".$e->getMessage());
			return false;
		}

    }/*}}}*/

}


?>
